#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <vector>
#include <semaphore.h>
#include <unistd.h>

#define num 16

class ringqueue
{
private:
    std::vector<int> q;
    int cap;
    sem_t space_sem;
    sem_t data_sem;
    int product_step;
    int consume_step;
public:
    ringqueue(int _cap = num):cap(_cap),q(_cap)
    {
        sem_init(&space_sem, 0, cap);
        sem_init(&data_sem, 0, 0);
        product_step = 0;
        consume_step = 0;
    }
    void pushdata(const int &data)
    {
        sem_wait(&space_sem);//P
        q[consume_step] = data;
        consume_step++;
        consume_step %= cap;
        sem_post(&data_sem);//V
    }
    void getdata(int &data)
    {
        sem_wait(&data_sem);
        data = q[product_step];
        product_step++;
        product_step %= cap;
        sem_post(&space_sem);
    }
    ~ringqueue()
    {
        sem_destroy(&data_sem);
        sem_destroy(&space_sem);
    }
};

void *consumer(void *arg)
{
    ringqueue* rq = (ringqueue*)arg;
    int data;
    while(1)
    {
        rq->getdata(data);
        std::cout <<"consume data done~" << data << std::endl;
        sleep(1);
    }
}

void *producter(void *arg)
{
    ringqueue *rq = (ringqueue*)arg;
    srand((unsigned long)time(NULL));
    while(1)
    {
        int data = rand()%1024;
        rq->pushdata(data);
        std::cout << "product data done~" << data << std::endl;
        sleep(1);
    }
}

int main()
{
    ringqueue rq;
    pthread_t c,p;

    pthread_create(&c, NULL, consumer, (void*)&rq);
    pthread_create(&p, NULL, producter, (void*)&rq);

    pthread_join(c, NULL);
    pthread_join(p, NULL);
    return 0;
}